Skip to content

gh-159303: Run asyncio's default exception handler in the task context - #159307

Open
drakeo338 wants to merge 2 commits into
python:mainfrom
drakeo338:claude/159303-fix
Open

drakeo338 wants to merge 2 commits into
python:mainfrom
drakeo338:claude/159303-fix

Conversation

@drakeo338

@drakeo338 drakeo338 commented Oct 13, 2026 •

Copy link
Copy Markdown

Fixes gh-159303.

With no custom handler set, call_exception_handler() called default_exception_handler() in the caller's context. gh-96704 made a custom handler run in the task's or handle's context, and its PR left the default handler for later. This moves the lookup into a helper and uses it for both.

Both handlers run in ctx.copy(). Without the copy, reporting from inside the task itself ('task': asyncio.current_task()) raises RuntimeError: cannot enter context, and a custom handler is silently skipped today.

Three tests in test_base_events:

  • the first fails on main (the default handler sees the caller's context);
  • the third fails on main (the custom handler is skipped);
  • the second passes on main and fails only if the copy is dropped.

The docs note both changes. The issue's repro now prints req-1 twice. ./python -m test --fast-ci -j8 test_asyncio passes.

Prepared with AI assistance (Claude), then reviewed and tested before submission.

@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #35116577 | 📁 Comparing a6373a7 against main (50082b8)

  🔍 Preview build  

2 files changed
± library/asyncio-eventloop.html
± whatsnew/changelog.html

@OsmnvAslan OsmnvAslan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this out locally: test_base_events passes, and the two new tests fail on main as described. The move into _get_exception_context() is a straight refactor of the existing lookup.

One behaviour change worth documenting: a custom handler used to run directly in the task's context, so a ContextVar.set() inside the handler was visible to the task afterwards. With ctx.copy() that write is now discarded (I confirmed both behaviours with a small script on main and on this branch). I think that's the right call, but a sentence in the versionchanged note would avoid surprising anyone relying on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

asyncio: default exception handler does not run in the task's context

2 participants